package cc.rengu.igas.momp.core.service.trans;

import cc.rengu.igas.momp.common.constant.CommonConstant;
import cc.rengu.igas.momp.common.dao.*;
import cc.rengu.igas.momp.common.dao.impl.*;
import cc.rengu.igas.momp.common.entity.*;
import cc.rengu.igas.momp.common.enums.*;
import cc.rengu.igas.momp.facade.request.ComboPaymentReversalRequest;
import cc.rengu.igas.momp.facade.response.ComboPaymentReversalResponse;
import cc.rengu.oltp.service.base.RadpService;
import cc.rengu.oltp.service.common.constant.AppConfigConstant;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.DbsUtil;
import cc.rengu.oltp.utility.util.XmlConfigUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import cc.rengu.utility.base.StringUtil;
import cc.rengu.utility.dbs.Database;
import com.alibaba.fastjson.JSONObject;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 合并支付冲正接口实现
 *
 * @author Jinan Liu
 * @version 1.0.0
 * @since 2020/4/2 17:47
 */
public class ComboPaymentReversalService extends RadpService {

    /**
     * 渠道交易日期
     */
    private String globalTxnDate;
    /**
     * 当前交易系统时间戳
     */
    private String globalTimeStamp;

    @Override
    protected int bizInit(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizProcess(String s, int i) {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();

        try {

            ComboPaymentReversalRequest comboPaymentReversalRequest = new ComboPaymentReversalRequest();
            ConvertUtil.convertOutput(comboPaymentReversalRequest);

            ComboPaymentReversalResponse comboPaymentReversalResponse = new ComboPaymentReversalResponse();
            comboPaymentReversalResponse.setHeader(comboPaymentReversalRequest.getHeader());
            BizResponse<ComboPaymentReversalResponse> bizResponse = new BizResponse<>();
            bizResponse.setResult(comboPaymentReversalResponse);

            /* 报文检查及全局变量赋值 */
            messageValidation(comboPaymentReversalRequest);

            /* 服务调用 */
            BizResponse<ComboPaymentReversalResponse> bizResponseNew = comboPaymentReversal(xmlTreeUtil, comboPaymentReversalRequest, comboPaymentReversalResponse);

            ConvertUtil.convertInput(bizResponseNew.getResult());

        } catch (BizException e) {
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, e.getCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, e.getMessage());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizTerminate(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 合并支付冲正
     *
     * @param xmlTreeUtil                  内部XML树
     * @param comboPaymentReversalRequest  (合并)支付冲正接口请求对象
     * @param comboPaymentReversalResponse (合并)支付冲正接口应答对象
     * @return cc.rengu.oltp.service.model.BizResponse<cc.rengu.igas.momp.facade.response.ComboPaymentReversalResponse> (合并)支付冲正接口应答对象
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/11 00:36
     */
    private BizResponse<ComboPaymentReversalResponse> comboPaymentReversal(XmlTreeUtil xmlTreeUtil, ComboPaymentReversalRequest comboPaymentReversalRequest, ComboPaymentReversalResponse comboPaymentReversalResponse) throws Exception {

        BizResponse<ComboPaymentReversalResponse> bizResponse = new BizResponse<>();

        String instId = comboPaymentReversalRequest.getHeader().getInstId();
        String origTraceNo = comboPaymentReversalRequest.getOrigTraceNo();

        /* 查询原交易订单流水信息 */
        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
        TMTxnOrder tmTxnOrder = tmTxnOrderMapper.selectTransactionOrderInfo(instId, globalTxnDate, origTraceNo);
        if (null == tmTxnOrder) {
            rglog.error("机构<{}>在<{}>的原交易订单流水信息<{}>失败!", instId, globalTxnDate, origTraceNo);
            throw new BizException(RespCodeEnum.FAILED_TO_CHECK_ORIGINAL_TXN_INFO_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_CHECK_ORIGINAL_TXN_INFO_ERROR.getRespDesc());
        }

        bizResponse.setRspSysId(ChannelEnum.MOMP.getChannelType());

        /* 判断订单状态是否可冲正处理 */
        int returnCode = checkAndProcessReversalProcedure(tmTxnOrder);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("机构<{}>在<{}>的原交易<{}>冲正原交易状态校验失败!", instId, globalTxnDate, origTraceNo);

            bizResponse.setRespCode(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespCode());
            bizResponse.setRespDesc(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespDesc());

            comboPaymentReversalResponse.setRespCode(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespCode());
            comboPaymentReversalResponse.setRespDesc(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespDesc());

        } else {

            rglog.info("机构<{}>在<{}>的原交易<{}>冲正原交易状态校验成功!", instId, globalTxnDate, origTraceNo);
            //进行订单冲正处理
            paymentReversalOperation(tmTxnOrder);

            bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());

            comboPaymentReversalResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            comboPaymentReversalResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());

        }

        bizResponse.setResult(comboPaymentReversalResponse);

        return bizResponse;
    }

    /**
     * 取原合并支付交易订单流水
     *
     * @param instId      法人机构号
     * @param transDate   原交易日期
     * @param origTraceNo 原交易流水号
     * @return java.util.List<cc.rengu.igas.momp.common.entity.TMTxnOrderDet> 订单明细表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/23 09:54
     */
    private List<TMTxnOrderDet> getOriginalTransactionOrderDetailInfo(String instId, String transDate, String origTraceNo) throws Exception {

        TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        return tmTxnOrderDetMapper.selectOriginalTransactionOrderDetailListInfo(instId, transDate, origTraceNo);
    }

    /**
     * 判断和处理冲正处理流程
     *
     * @param tmTxnOrder 订单流水表
     * @return int 返回码
     * @author Jinan Liu
     * @since 2020/4/23 10:16
     */
    private int checkAndProcessReversalProcedure(TMTxnOrder tmTxnOrder) {

        try {
            String bizStatus = tmTxnOrder.getBizStatus();
            /* 判断原交易订单状态 */
            if (BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode().equals(bizStatus) ||
                    BizStatusEnum.PROCESS_FAILED.getBizStatusCode().equals(bizStatus) ||
                    BizStatusEnum.PROCESS_PAYMENT_REVERSED.getBizStatusCode().equals(bizStatus) ||
                    BizStatusEnum.PROCESS_REFUND_REVERSED.getBizStatusCode().equals(bizStatus)) {
                /* 消费冲正流程 */
                rglog.info("机构<{}>在<{}>的原交易<{}> 支付状态<{}>,可继续冲正流程处理!", tmTxnOrder.getInstId(), tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum(), bizStatus);
                return CommonConstant.PROCESS_SUCCESS;
            } else if (BizStatusEnum.PROCESSING.getBizStatusCode().equals(bizStatus)) {
                /* 原交易正在进行中,不可冲正 */
                rglog.error("机构<{}>在<{}>的原交易<{}>正在进行中,不可冲正!", tmTxnOrder.getInstId(), tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum());
                return CommonConstant.PROCESS_FAILED;
            } else if (BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode().equals(bizStatus) || BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode().equals(bizStatus)) {
                /* 原交易已部分或全额退货，不可冲正 */
                rglog.error("机构<{}>在<{}>的原交易<{}>已部分或全额退货,不可冲正!", tmTxnOrder.getInstId(), tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum());
                return CommonConstant.PROCESS_FAILED;
            } else {
                /* 原交易状态异常，不可冲正 */
                return CommonConstant.PROCESS_FAILED;
            }
        } catch (Exception e) {
            rglog.error("冲正处理失败! 异常信息:<{}>", StringUtil.ExceptionToString(e));
            return CommonConstant.PROCESS_FAILED;
        }

    }

    /**
     * 消费冲正处理流程
     *
     * @param tmTxnOrder TMTxnOrder
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/23 10:13
     */
    private void paymentReversalOperation(TMTxnOrder tmTxnOrder) throws Exception {

        int returnCode;
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();

        String instId = tmTxnOrder.getInstId();
        String transDate = tmTxnOrder.getTxnDate();
        String origTraceNo = tmTxnOrder.getFrontSeqNum();

        String bizStatus = tmTxnOrder.getBizStatus();
        if (BizStatusEnum.PROCESS_FAILED.getBizStatusCode().equals(bizStatus) ||
                BizStatusEnum.PROCESS_PAYMENT_REVERSED.getBizStatusCode().equals(bizStatus) ||
                BizStatusEnum.PROCESS_REFUND_REVERSED.getBizStatusCode().equals(bizStatus)) {
            /* 直接返回冲正成功 */
            rglog.info("机构<{}>在<{}>的原交易<{}> 状态为<{}>,无需继续冲正处理(02:业务处理失败 20：已消费冲正 AA:已退货冲正)，返回冲正成功!",
                    tmTxnOrder.getInstId(), tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum(), bizStatus);
            return;
        }

        /* 开启数据库事务 */
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.MOMP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.MOMP_POOL_NAME);
        }
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();

        String orderRemark = tmTxnOrder.getOrderRemark();
        //判断如果是没有优惠的，并且原交易是成功的，需要更新原交易为已冲正（这里不用判断无优惠原交易是失败的情况，如果失败在上步就已经返回）
        if (BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode().equals(bizStatus) && CommonConstant.DISCOUNT_FLAG_FALSE_CHECK_FLAG_FALSE.equals(orderRemark)) {
            /* 更新订单流水表业务状态 */
            tmTxnOrder.setBizStatus(BizStatusEnum.PROCESS_PAYMENT_REVERSED.getBizStatusCode());
            tmTxnOrder.setUpdateTime(globalTimeStamp);
            returnCode = updateTxnOrderBizStatusInfo(tmTxnOrder);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                rglog.error("更新订单流水表流水<{}>失败!所有数据库操作回滚!", tmTxnOrder.getFrontSeqNum());
                /* 事务处理失败关闭数据库事务 */
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespDesc());
            }
            rglog.info("机构<{}>在<{}>的原交易<{}> 为成功的交易，但订单无任何优惠信息! orderRemark：<{}>,更新原交易为已冲正，返回冲正成功！", instId, transDate, origTraceNo, orderRemark);
            /* 事务处理成功关闭数据库事务 */
            dbsUtil.dbsEndTransaction(true);
            return;
        }

        /* 查询原始交易订单明细 */
        List<TMTxnOrderDet> tmTxnOrderDetList = getOriginalTransactionOrderDetailInfo(instId, transDate, origTraceNo);
        if (null == tmTxnOrderDetList || tmTxnOrderDetList.isEmpty()) {
            rglog.error("取机构<{}>在<{}>的流水号<{}>的订单明细信息失败!", instId, transDate, origTraceNo);
            throw new BizException(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespDesc());
        }

        try {
            /* 卡券类处理流程 */
            paymentReversalCouponMcProcedure(dbsUtil, tmTxnOrderDetList);

            /* 减免类处理流程 */
            paymentReversalMoneyOffMcProcedure(dbsUtil, tmTxnOrderDetList);

            /* 商户手续费优惠类处理流程 */
            paymentReversalMchntFeeDiscountMcProcedure(dbsUtil, tmTxnOrderDetList);

            /* 更新订单流水表业务状态 */
            tmTxnOrder.setBizStatus(BizStatusEnum.PROCESS_PAYMENT_REVERSED.getBizStatusCode());
            tmTxnOrder.setUpdateTime(globalTimeStamp);
            returnCode = updateTxnOrderBizStatusInfo(tmTxnOrder);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                rglog.error("更新订单流水表失败!所有数据库操作回滚!");
                /* 事务处理失败关闭数据库事务 */
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespDesc());
            }

            /* 事务处理成功关闭数据库事务 */
            dbsUtil.dbsEndTransaction(true);

        } catch (Exception e) {

            /* 事务处理失败关闭数据库事务 */
            dbsUtil.dbsEndTransaction(false);

            rglog.error("冲正处理失败! 异常信息:<{}>", StringUtil.ExceptionToString(e));
            throw new BizException(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespDesc());
        }
    }

    /**
     * 消费冲正-卡券部分处理业务流程
     *
     * @param dbsUtil           数据库操作工具类
     * @param tmTxnOrderDetList 订单明细表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/23 10:34
     */
    private void paymentReversalCouponMcProcedure(DbsUtil dbsUtil, List<TMTxnOrderDet> tmTxnOrderDetList) throws Exception {

        List<TMTxnOrderDet> couponOrderDetList = tmTxnOrderDetList.stream().filter(item -> checkCouponMcType(McTypeEnum.MC_TYPE_CP.getMcTypeCode(), item.getMcType())).collect(Collectors.toList());
        for (TMTxnOrderDet tmTxnOrderDet : couponOrderDetList) {
            reverseSingleCouponSubOrder(dbsUtil, tmTxnOrderDet);
        }
    }

    /**
     * 消费冲正-满减部分处理业务流程
     *
     * @param dbsUtil           数据库操作工具类
     * @param tmTxnOrderDetList 订单明细表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/23 10:35
     */
    private void paymentReversalMoneyOffMcProcedure(DbsUtil dbsUtil, List<TMTxnOrderDet> tmTxnOrderDetList) throws Exception {

        List<TMTxnOrderDet> moneyOffOrderDetList = tmTxnOrderDetList.stream().filter(item -> checkCouponMcType(McTypeEnum.MC_TYPE_MO.getMcTypeCode(), item.getMcType())).collect(Collectors.toList());
        for (TMTxnOrderDet tmTxnOrderDet : moneyOffOrderDetList) {
            reverseSingleMoneyOffSubOrder(dbsUtil, tmTxnOrderDet);
        }
    }

    /**
     * 消费冲正-商户手续费部分处理业务流程
     *
     * @param dbsUtil           数据库操作工具类
     * @param tmTxnOrderDetList 订单明细表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/23 10:34
     */
    private void paymentReversalMchntFeeDiscountMcProcedure(DbsUtil dbsUtil, List<TMTxnOrderDet> tmTxnOrderDetList) throws Exception {

        List<TMTxnOrderDet> mchntFeeDiscountOrderDetList = tmTxnOrderDetList.stream().filter(item -> checkCouponMcType(McTypeEnum.MC_TYPE_MFD.getMcTypeCode(), item.getMcType())).collect(Collectors.toList());
        for (TMTxnOrderDet tmTxnOrderDet : mchntFeeDiscountOrderDetList) {
            reverseSingleMchntFeeDiscountSubOrder(dbsUtil, tmTxnOrderDet);
        }
    }

    /**
     * 处理单个子订单的卡券明细
     *
     * @param dbsUtil       数据库操作工具类
     * @param tmTxnOrderDet 订单明细表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/23 10:42
     */
    private void reverseSingleCouponSubOrder(DbsUtil dbsUtil, TMTxnOrderDet tmTxnOrderDet) throws Exception {

        /* 扣减对客类营销活动统计值 */
        reverseToClientMcStatistics(dbsUtil, tmTxnOrderDet);

        /* 更新卡券状态 */
        reverseCouponInfo(dbsUtil, tmTxnOrderDet);

        /* 更新原订单明细状态 */
        tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_PAYMENT_REVERSED.getBizStatusCode());
        tmTxnOrderDet.setUpdateTime(globalTimeStamp);
        TMTxnOrderDetMapper TmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        int returnCode = TmTxnOrderDetMapper.updateTmTxnOrderDetByKey(tmTxnOrderDet);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("更新订单流水表失败!所有数据库操作回滚!");
            /* 事务处理失败关闭数据库事务 */
            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespDesc());
        }
    }

    /**
     * 处理单个子订单的满减明细
     *
     * @param dbsUtil       数据库操作工具类
     * @param tmTxnOrderDet 订单明细表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/23 10:57
     */
    private void reverseSingleMoneyOffSubOrder(DbsUtil dbsUtil, TMTxnOrderDet tmTxnOrderDet) throws Exception {

        /* 扣减对客类营销活动统计值 */
        reverseToClientMcStatistics(dbsUtil, tmTxnOrderDet);

        /* 更新原订单明细状态 */
        tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_PAYMENT_REVERSED.getBizStatusCode());
        tmTxnOrderDet.setUpdateTime(globalTimeStamp);
        TMTxnOrderDetMapper TmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        int returnCode = TmTxnOrderDetMapper.updateTmTxnOrderDetByKey(tmTxnOrderDet);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("更新订单流水表失败!所有数据库操作回滚!");
            /* 事务处理失败关闭数据库事务 */
            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespDesc());
        }
    }

    /**
     * 处理单个子订单的商户手续费优惠明细
     *
     * @param dbsUtil       数据库操作工具类
     * @param tmTxnOrderDet 订单明细表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/23 10:57
     */
    private void reverseSingleMchntFeeDiscountSubOrder(DbsUtil dbsUtil, TMTxnOrderDet tmTxnOrderDet) throws Exception {

        /* 扣减商户手续费优惠营销活动统计值 */
        reverseMchntFeeDiscountMcStatistics(dbsUtil, tmTxnOrderDet);

        /* 更新原订单明细状态 */
        tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_PAYMENT_REVERSED.getBizStatusCode());
        tmTxnOrderDet.setUpdateTime(globalTimeStamp);
        TMTxnOrderDetMapper TmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        int returnCode = TmTxnOrderDetMapper.updateTmTxnOrderDetByKey(tmTxnOrderDet);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("更新订单流水表失败!所有数据库操作回滚!");
            /* 事务处理失败关闭数据库事务 */
            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespDesc());
        }
    }

    /**
     * 处理对客类营销活动统计数据
     *
     * @param dbsUtil       数据库操作工具类
     * @param tmTxnOrderDet 订单明细表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/23 18:22
     */
    private void reverseToClientMcStatistics(DbsUtil dbsUtil, TMTxnOrderDet tmTxnOrderDet) throws Exception {
        BigDecimal zero = BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal oriMchntSubsidy = new BigDecimal(tmTxnOrderDet.getMchntSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal oriBankSubsidy = new BigDecimal(tmTxnOrderDet.getBankSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        /* 更新对客户营销活动单日统计表表数据 */
        TMStat2CDay tmStat2CDay = new TMStat2CDay();

        tmStat2CDay.setInstId(tmTxnOrderDet.getInstId());
        tmStat2CDay.setMcNo(tmTxnOrderDet.getMcNo());
        tmStat2CDay.setTxnDate(tmTxnOrderDet.getTxnDate());
        tmStat2CDay.setRuleIndex(tmTxnOrderDet.getRuleIndex());
        tmStat2CDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStat2CDay.setUpdateTime(globalTimeStamp);

        BigDecimal minusOne = BigDecimal.ZERO.subtract(BigDecimal.ONE).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        String minusOneString = minusOne.toString();
        String totalSubsidy = new BigDecimal(tmTxnOrderDet.getSubsidy()).multiply(minusOne).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
        String bankSubsidy = new BigDecimal(tmTxnOrderDet.getBankSubsidy()).multiply(minusOne).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
        String mchntSubsidy = new BigDecimal(tmTxnOrderDet.getMchntSubsidy()).multiply(minusOne).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
        String txnQtyAcc = new BigDecimal(tmTxnOrderDet.getOriginalAmt()).multiply(minusOne).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();

        tmStat2CDay.setTotalQtyAcc(minusOneString);
        tmStat2CDay.setTotalAmtAcc(totalSubsidy);
        if (BigDecimal.ZERO.compareTo(oriBankSubsidy) == CommonConstant.ZERO) {
            tmStat2CDay.setBankQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        } else {
            tmStat2CDay.setBankQtyAcc(minusOneString);
        }
        tmStat2CDay.setBankAmtAcc(bankSubsidy);
        tmStat2CDay.setTxnQtyAcc(txnQtyAcc);
        if (BigDecimal.ZERO.compareTo(oriMchntSubsidy) == CommonConstant.ZERO) {
            tmStat2CDay.setMchntQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        } else {
            tmStat2CDay.setMchntQtyAcc(minusOneString);
        }

        tmStat2CDay.setMchntAmtAcc(mchntSubsidy);

        tmStat2CDay.setMchntQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStat2CDay.setExposureQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStat2CDay.setExposurePeopleQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStat2CDay.setAvgTotalAmt(CommonConstant.ZERO_AMOUNT);
        tmStat2CDay.setAvgBankAmt(CommonConstant.ZERO_AMOUNT);
        tmStat2CDay.setAvgMchntAmt(CommonConstant.ZERO_AMOUNT);
        tmStat2CDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStat2CDay.setCreateTime(globalTimeStamp);
        tmStat2CDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStat2CDay.setUpdateTime(globalTimeStamp);

        TMStat2CDayMapper tmStat2CDayMapper = new TMStat2CDayMapperImpl();
        int returnCode = tmStat2CDayMapper.updateToClientMcDayStatistics(tmStat2CDay);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            if (Database.DBS_NOT_FOUND == returnCode) {
                int insertReturnCode = tmStat2CDayMapper.insertSingleToClientMcDayStatistics(tmStat2CDay);
                if (CommonConstant.PROCESS_SUCCESS != insertReturnCode) {
                    rglog.error("插入对客户营销活动单日统计表规则为<{}>数据失败!", tmStat2CDay.getRuleIndex());
                    throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
                }
            } else {
                rglog.error("更新对客户营销活动单日统计表数据失败!");
                throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
            }
        }

        //如果当规则不是0 ，则还需要更新规则为0的记录（走到这，规则肯定不为0）
        if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStat2CDay.getRuleIndex())) {
            tmStat2CDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);

            returnCode = tmStat2CDayMapper.updateToClientMcDayStatistics(tmStat2CDay);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                if (Database.DBS_NOT_FOUND == returnCode) {
                    int insertReturnCode2 = tmStat2CDayMapper.insertSingleToClientMcDayStatistics(tmStat2CDay);
                    if (CommonConstant.PROCESS_SUCCESS != insertReturnCode2) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>对客户营销活动单日统计表失败! RETURN_CODE=<{}>", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的对客户营销活动单日统计表数据失败! RETURN_CODE=<{}>", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }
        }

        /* 更新对客户营销活动商户单日统计表的数据 */
        TMStat2CMchntDay tmStat2CMchntDay = new TMStat2CMchntDay();
        tmStat2CMchntDay.setInstId(tmTxnOrderDet.getInstId());
        tmStat2CMchntDay.setTxnDate(tmTxnOrderDet.getTxnDate());
        tmStat2CMchntDay.setMcNo(tmTxnOrderDet.getMcNo());
        tmStat2CMchntDay.setMchntNo(tmTxnOrderDet.getMchntNo());
        if (oriMchntSubsidy.compareTo(zero) > CommonConstant.ZERO) {
            tmStat2CMchntDay.setTotalQtyAcc(minusOneString);
        } else {
            tmStat2CMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        tmStat2CMchntDay.setTotalAmtAcc(mchntSubsidy);
        tmStat2CMchntDay.setBankAmtAcc(bankSubsidy);
        if (oriBankSubsidy.compareTo(zero) > CommonConstant.ZERO) {
            tmStat2CMchntDay.setBankQtyAcc(minusOneString);
        } else {
            tmStat2CMchntDay.setBankQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        tmStat2CMchntDay.setAvgBankAmtAcc(CommonConstant.ZERO_AMOUNT);
        tmStat2CMchntDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStat2CMchntDay.setUpdateTime(globalTimeStamp);

        tmStat2CMchntDay.setAvgAmtAcc(CommonConstant.ZERO_AMOUNT);
        tmStat2CMchntDay.setTxnAmtAcc(txnQtyAcc);
        tmStat2CMchntDay.setExposureQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStat2CMchntDay.setExposurePeopleQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStat2CMchntDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStat2CMchntDay.setCreateTime(globalTimeStamp);
        tmStat2CMchntDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);

        TMStat2CMchntDayMapper tmStat2CMchntDayMapper = new TMStat2CMchntDayMapperImpl();
        returnCode = tmStat2CMchntDayMapper.updateToClientMcMchntDayStatistics(tmStat2CMchntDay);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            if (Database.DBS_NOT_FOUND == returnCode) {
                tmStat2CMchntDay.setCreateTime(globalTimeStamp);
                tmStat2CMchntDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
                int insertReturnCode = tmStat2CMchntDayMapper.insertSingleToClientMcMchntDayStatistics(tmStat2CMchntDay);
                if (CommonConstant.PROCESS_SUCCESS != insertReturnCode) {
                    rglog.error("插入对客户营销活动商户单日统计表规则为<{}>数据失败!", tmStat2CDay.getRuleIndex());
                    throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
                }
            } else {
                rglog.error("更新对客户营销活动商户单日统计表数据失败!");
                throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
            }
        }
    }

    /**
     * 处理卡券信息
     *
     * @param dbsUtil       数据库操作工具类
     * @param tmTxnOrderDet 订单明细表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/23 18:24
     */
    private void reverseCouponInfo(DbsUtil dbsUtil, TMTxnOrderDet tmTxnOrderDet) throws Exception {

        /* 更新卡券信息表 */
        TMCouponInfo tmCouponInfo = new TMCouponInfo();
        tmCouponInfo.setInstId(tmTxnOrderDet.getInstId());
        tmCouponInfo.setCouponStatus(CouponStatusEnum.NOT_REDEEMED.getCouponStatusCode());
        tmCouponInfo.setOrderId("");
        tmCouponInfo.setRedeemTime("");

        JSONObject relativeDataJson = JSONObject.parseObject(tmTxnOrderDet.getRelativeData());
        //原商户订单明细金额
        String couponNo = relativeDataJson.get("couponNo").toString();
        tmCouponInfo.setCouponNo(couponNo);

        CouponInfoMapper couponInfoMapper = new CouponInfoMapperImpl();
        int returnCode = couponInfoMapper.reverseRedeemedCoupon(tmCouponInfo);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("冲正处理，更新卡券信息表卡券状态失败!");
            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespDesc());
        }
    }

    /**
     * 处理商户手续费营销活动统计数据
     *
     * @param dbsUtil       数据库操作工具类
     * @param tmTxnOrderDet 订单明细表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/23 18:25
     */
    private void reverseMchntFeeDiscountMcStatistics(DbsUtil dbsUtil, TMTxnOrderDet tmTxnOrderDet) throws Exception {
        //关联信息
        String relativeData = tmTxnOrderDet.getRelativeData();
        JSONObject relativeDataJson = JSONObject.parseObject(relativeData);

        //原交易登记的活动规则编号
        String ruleIndex = tmTxnOrderDet.getRuleIndex();

        rglog.info("机构<{}> 交易日期<{}> 流水<{}> 开始回退统计数据...", tmTxnOrderDet.getInstId(), tmTxnOrderDet.getTxnDate(), tmTxnOrderDet.getFrontSeqNum());

        String disTxAmt = tmTxnOrderDet.getDisTxAmt();
        String txnAmtAcc;
        if (null != disTxAmt) {
            txnAmtAcc = new BigDecimal(disTxAmt).multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
        } else {
            //获取明细中的订单金额（商户清算金额）
            String orderAmtString = relativeDataJson.get("orderAmt").toString();
            txnAmtAcc = new BigDecimal(orderAmtString).multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
        }
        //获取明细中总补贴金额
        BigDecimal totalSubsidyString = new BigDecimal(tmTxnOrderDet.getSubsidy()).multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);


        TMStatMfdDay tmStatMfdDay1 = new TMStatMfdDay();
        tmStatMfdDay1.setInstId(tmTxnOrderDet.getInstId());
        tmStatMfdDay1.setTxnDate(tmTxnOrderDet.getTxnDate());
        tmStatMfdDay1.setMcNo(tmTxnOrderDet.getMcNo());
        tmStatMfdDay1.setRuleIndex(ruleIndex);
        tmStatMfdDay1.setTotalQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
        tmStatMfdDay1.setTotalAmtAcc(totalSubsidyString.toString());
        tmStatMfdDay1.setTxnQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
        tmStatMfdDay1.setTxnAmtAcc(txnAmtAcc);
        tmStatMfdDay1.setMchntQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdDay1.setMchntOldQualified(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdDay1.setMchntNewQualified(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdDay1.setMchntExitQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdDay1.setAvgAmt(CommonConstant.ZERO_AMOUNT);
        tmStatMfdDay1.setPaidAmt(CommonConstant.ZERO_AMOUNT);
        tmStatMfdDay1.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatMfdDay1.setCreateTime(globalTimeStamp);
        tmStatMfdDay1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatMfdDay1.setUpdateTime(globalTimeStamp);

        rglog.info("机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动单日统计表...", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex());
        /* 手续费减免活动单日统计表 */
        TMStatMfdDayMapper tmStatMfdDayMapper = new TMStatMfdDayMapperImpl();
        int returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay1);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            if (Database.DBS_NOT_FOUND == returnCode) {
                int returnCode2 = tmStatMfdDayMapper.insertTMStatMfdDay(tmStatMfdDay1);
                if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                    /* 插入数据失败 */
                    rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            } else {
                /* 更新数据失败 */
                rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
            }
        }

        //如果当规则不是0 ，则还需要更新规则为0的记录
        if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdDay1.getRuleIndex())) {
            tmStatMfdDay1.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);
            rglog.info("机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动单日统计表...", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex());
            returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay1);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                if (Database.DBS_NOT_FOUND == returnCode) {
                    int returnCode2 = tmStatMfdDayMapper.insertTMStatMfdDay(tmStatMfdDay1);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }
        }

        String mchntNo = tmTxnOrderDet.getMchntNo();
        MchntInfoMapper mchntInfoMapper = new MchntInfoMapperImpl();
        TBMchntBaseInfo mchntBaseInfo = mchntInfoMapper.selectMompMchntBaseInfoByPrimaryKey(tmStatMfdDay1.getInstId(), mchntNo);
        if (null == mchntBaseInfo) {
            //查询不到商户信息，流程结束
            rglog.error("查询商户基本信息信息失败, INST_ID=<{}>, MCHNT_NO=<{}>", tmStatMfdDay1.getInstId(), mchntNo);
            throw new BizException(RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespDesc());
        }
        //商户性质
        String mchntType = mchntBaseInfo.getMchntType();
        //独立营销活动标识
        String idpdCmavyFlg = mchntBaseInfo.getMarketFlag();
        //连锁商户号
        String chainMchntNo = mchntBaseInfo.getChainMchntNo();
        //是否独立维护商户资料
        String independentDataFlag = mchntBaseInfo.getIndependentDataFlag();
        if (CommonConstant.YES.equals(independentDataFlag) && MchntTypeEnum.CHAIN_MCHNT_STORE.getMchntType().equals(mchntType) && CommonConstant.ZERO_COMMON_CONSTANT.equals(idpdCmavyFlg)) {
            rglog.info("商户<{}> 商户类型为11:连锁商户门店，商户独立营销活动标识为<{}> 是否独立维护商户资料<{}> 原正向交易计算营销时根据上级商户<{}> 获取营销活动计算的!", mchntNo, idpdCmavyFlg, independentDataFlag, chainMchntNo);
            mchntNo = chainMchntNo;
        } else {
            rglog.info("商户<{}> 是否独立维护商户资料<{}> 商户类型为<{}> 原正向交易无需判断独立营销活动标识，均使用当前商户号计算的营销！", mchntBaseInfo.getMchntNo(), independentDataFlag, idpdCmavyFlg);
        }

        /* 手续费减免活动商户单日统计表 */
        TMStatMfdMchntDay tmStatMfdMchntDay1 = new TMStatMfdMchntDay();
        tmStatMfdMchntDay1.setInstId(tmTxnOrderDet.getInstId());
        tmStatMfdMchntDay1.setTxnDate(globalTxnDate);
        tmStatMfdMchntDay1.setMcNo(tmTxnOrderDet.getMcNo());
        tmStatMfdMchntDay1.setMchntNo(mchntNo);
        tmStatMfdMchntDay1.setRuleIndex(ruleIndex);
        tmStatMfdMchntDay1.setTotalQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
        tmStatMfdMchntDay1.setTotalAmtAcc(totalSubsidyString.toString());
        tmStatMfdMchntDay1.setTxnQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
        tmStatMfdMchntDay1.setTxnAmtAcc(txnAmtAcc);
        tmStatMfdMchntDay1.setTotalAvgAmt(CommonConstant.ZERO_AMOUNT);
        tmStatMfdMchntDay1.setExitStatus(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdMchntDay1.setCashbackStatus(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdMchntDay1.setCashbackAmt(CommonConstant.ZERO_AMOUNT);
        tmStatMfdMchntDay1.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatMfdMchntDay1.setCreateTime(globalTimeStamp);
        tmStatMfdMchntDay1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatMfdMchntDay1.setUpdateTime(globalTimeStamp);

        rglog.info("机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表...", tmStatMfdMchntDay1.getInstId(), tmStatMfdMchntDay1.getMcNo(), tmStatMfdMchntDay1.getRuleIndex());
        /* 手续费减免活动商户单日统计表 */
        TMStatMfdMchntDayMapper tmStatMfdMchntDayMapper = new TMStatMfdMchntDayMapperImpl();
        int returnCode2 = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay1);
        if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
            if (Database.DBS_NOT_FOUND == returnCode) {
                int returnCode3 = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay1);
                if (CommonConstant.PROCESS_SUCCESS != returnCode3) {
                    /* 插入数据失败 */
                    rglog.error("插入法人机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay1.getInstId(), tmStatMfdMchntDay1.getMcNo(), tmStatMfdMchntDay1.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            } else {
                /* 更新数据失败 */
                rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay1.getInstId(), tmStatMfdMchntDay1.getMcNo(), tmStatMfdMchntDay1.getRuleIndex(), returnCode);
                throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
            }
        }

        //如果当规则不是0 ，则还需要更新规则为0的记录
        if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdMchntDay1.getRuleIndex())) {
            tmStatMfdMchntDay1.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);
            rglog.info("机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表...", tmStatMfdMchntDay1.getInstId(), tmStatMfdMchntDay1.getMcNo(), tmStatMfdMchntDay1.getRuleIndex());
            returnCode2 = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay1);
            if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                if (Database.DBS_NOT_FOUND == returnCode) {
                    int returnCode3 = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay1);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode3) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay1.getInstId(), tmStatMfdMchntDay1.getMcNo(), tmStatMfdMchntDay1.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay1.getInstId(), tmStatMfdMchntDay1.getMcNo(), tmStatMfdMchntDay1.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }
        }
    }

    /**
     * 更新订单流水表业务状态
     *
     * @param tmTxnOrder 订单流水表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/23 11:40
     */
    private int updateTxnOrderBizStatusInfo(TMTxnOrder tmTxnOrder) throws Exception {

        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
        int returnCode = tmTxnOrderMapper.updateOriginalTransactionOrderBizStatus(tmTxnOrder);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("更新订单流水表业务状态失败!");
            return CommonConstant.PROCESS_FAILED;
        } else {
            return CommonConstant.PROCESS_SUCCESS;
        }
    }


    /**
     * 根据检查类型和营销活动类型区分是否是某种类型的营销活动
     *
     * @param checkType 检查类型
     * @param mcType    营销活动类型
     * @return boolean 营销活动类型是否匹配
     * @author Jinan Liu
     * @since 2020/4/23 11:20
     */
    private boolean checkCouponMcType(String checkType, String mcType) {

        if (null != checkType && null != mcType) {
            switch (Objects.requireNonNull(McTypeEnum.getByValue(checkType))) {
                case MC_TYPE_CP:
                    switch (Objects.requireNonNull(McTypeEnum.getByValue(mcType))) {
                        case COUPON_ALL:
                        case COUPON_FREE:
                        case COUPON_PAID:
                            return true;
                        default:
                            return false;
                    }
                case MC_TYPE_MO:
                    switch (Objects.requireNonNull(McTypeEnum.getByValue(mcType))) {
                        case REDUCTION_FIXED_AMOUNT:
                        case REDUCTION_RANDOM_AMOUNT:
                        case REDUCTION_FIXED_RATE:
                        case REDUCTION_RANDOM_RATE:
                            return true;
                        default:
                            return false;
                    }
                case MC_TYPE_MFD:
                    return McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode().equals(mcType);
                default:
                    return false;
            }
        } else {
            return false;
        }

    }

    /**
     * 报文检查及全局变量赋值
     *
     * @param comboPaymentReversalRequest (合并)支付冲正接口请求对象
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/7/25 15:08
     */
    private void messageValidation(ComboPaymentReversalRequest comboPaymentReversalRequest) throws BizException {

        if (StringUtil.isNullorEmpty(comboPaymentReversalRequest.getHeader().getTransDate())) {
            rglog.error("交易日期必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            globalTxnDate = comboPaymentReversalRequest.getHeader().getTransDate();
        }

        if (StringUtil.isNullorEmpty(comboPaymentReversalRequest.getHeader().getTransTime())) {
            rglog.error("交易时间必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (StringUtil.isNullorEmpty(comboPaymentReversalRequest.getHeader().getInstId())) {
            rglog.error("法人机构号必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (StringUtil.isNullorEmpty(comboPaymentReversalRequest.getHeader().getTraceNo())) {
            rglog.error("流水号必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        globalTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        if (StringUtil.isNullorEmpty(comboPaymentReversalRequest.getOrigTraceNo())) {
            rglog.error("需要上送原交易流水号!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }
    }
}
